package com.liu.map
{
	import com.adobe.utils.AGALMiniAssembler;
	import com.liu.debug.Console;
	import com.liu.load.LoadInfo;
	import com.liu.load.LoadManager;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.Stage;
	import flash.display.Stage3D;
	import flash.display3D.Context3D;
	import flash.display3D.Context3DBlendFactor;
	import flash.display3D.Context3DCompareMode;
	import flash.display3D.Context3DProgramType;
	import flash.display3D.Context3DRenderMode;
	import flash.display3D.Context3DTextureFormat;
	import flash.display3D.Context3DTriangleFace;
	import flash.display3D.Context3DVertexBufferFormat;
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.Program3D;
	import flash.display3D.VertexBuffer3D;
	import flash.display3D.textures.Texture;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.system.System;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	
	import org.ijelly.findPath.Cell;
	import org.ijelly.findPath.NavMesh;
	import org.ijelly.geom.Block;
	import org.ijelly.geom.Triangle;
	import org.ijelly.geom.Vector2f;
	import org.molehill.Role;
	import org.molehill.SpriteMoleHill;
	import org.molehill.TexturePool;
	import org.osmf.events.TimeEvent;

	public class MapManager
	{
		private var _baseUrl:String = 'file:///C:/Documents%20and%20Settings/Administrator/My%20Documents/map/';
		/*file:///C:/Documents%20and%20Settings/Administrator/My%20Documents/map/CJ301/CJ301.navmap*/
		/*file:///D:/My%20Documents/map/CJ301/CJ301.mapedit*/
		private var _mapName:String = 'CJ301';
		private var stage:Stage;
		private var _mapContainer:MapContainer;
		private var _mapdataDIC:Object;
		
		private var _loadListDIC:Object;
		
		private var _mapWidth:int;
		private var _mapHeight:int;
		private var _picw:int
		private var _pich:int; 
		
		private var _loadNum:int;
		private var _allNum:int;
		private var _currentPoint:String;
		
		private var _cellV:Vector.<Cell> = new Vector.<Cell>();
		private var _blockV:Vector.<Block> = new Vector.<Block>;
		
		
		private var _context3D:Context3D;
		private var _shaderProgram:Program3D;
		private var _indexBuffer:IndexBuffer3D;
		private var _buffer:VertexBuffer3D;
		private var _viewMatrix:Matrix3D;
		
		private var _renderList:Vector.<SpriteMoleHill>;
		
		private var role:Role;
		private var newrole:Role;
		
		public var nav:NavMesh;
		public function MapManager(stage:Stage)
		{
			this.stage = stage;
			//this._mapContainer = mapContainer;
			//this._mapContainer.mapManager = this;
			initMolehill();
		}
		private function initMolehill():void{
			var stage3D:Stage3D = stage.stage3Ds[0];
			stage3D.addEventListener(Event.CONTEXT3D_CREATE, creatMolehill);
			stage3D.requestContext3D(Context3DRenderMode.AUTO);
		}
		private function creatMolehill(e:Event):void 
		{
			var stage3D:Stage3D = e.target as Stage3D;
			
			_context3D = stage3D.context3D;
			if (_context3D == null)
			{
				trace("oh no, context is null!");
				return;
			}
			
			trace(_context3D.driverInfo);
			try
			{
				_context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2, false);		
			}
			catch (e:Error)
			{
				trace(e);
			}
			
			_context3D.enableErrorChecking = true;
			var vertexShader:Array =
				[
					"dp4 op.x, va0, vc0", //4x4 matrix transform from 0 to output clipspace
					"dp4 op.y, va0, vc1",
					"dp4 op.z, va0, vc2",
					"dp4 op.w, va0, vc3",
					"mov v0, va1.xyzw"    //copy texcoord from 1 to fragment program
				];
			var vertexAssembler:AGALMiniAssembler = new AGALMiniAssembler();
			vertexAssembler.assemble(flash.display3D.Context3DProgramType.VERTEX, vertexShader.join("\n"));
			
			var fragmentShader:Array =
				[
					"mov ft0, v0			\n" ,
					"tex ft1, ft0, fs1 <2d>	\n" ,	// sample texture 0
					"mov oc, ft1\n"
				];
			var fragmentAssembler:AGALMiniAssembler = new AGALMiniAssembler();
			fragmentAssembler.assemble(flash.display3D.Context3DProgramType.FRAGMENT, fragmentShader.join("\n"));
			
			_shaderProgram = _context3D.createProgram();
			_shaderProgram.upload(vertexAssembler.agalcode, fragmentAssembler.agalcode);
			
			_indexBuffer = _context3D.createIndexBuffer(6);
			_indexBuffer.uploadFromVector(Vector.<uint>([0, 1, 2, 0, 2, 3 ]), 0, 6);
			
			_buffer     = _context3D.createVertexBuffer(4, 4);
			_buffer.uploadFromVector(Vector.<Number>
				([
					-1.0, 1.0, 0.0, 1.0,
					-1.0,-1.0, 0.0, 0.0,
					1.0,-1.0, 1.0, 0.0,
					1.0, 1.0, 1.0, 1.0
				]), 0, 4);
			_renderList = new Vector.<SpriteMoleHill>;
			_context3D.setVertexBufferAt(0, _buffer, 0, Context3DVertexBufferFormat.FLOAT_2); //xy
			_context3D.setVertexBufferAt(1, _buffer, 2, Context3DVertexBufferFormat.FLOAT_2); //uv
			
			_context3D.setBlendFactors(Context3DBlendFactor.ONE, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA);
			
			_context3D.setProgram(_shaderProgram);
			
			initMatrix();
			
			_mapContainer = new MapContainer(_context3D,stage,this);
			_mapContainer.viewMatrix = _viewMatrix;
			_mapContainer.indexBuffer = this._indexBuffer;
			
			TexturePool.instance = new TexturePool(_context3D);
			
			var arymodel:Array = ["FAngel","MAngel","FHuman","MHuman","FMerfolk","MMerfolk","FTiaer","MTiaer"];
			
			for(var i:int;i<1;i++){
				role = new Role(_context3D,arymodel[int(7*Math.random())]);
				role.viewMatrix = _viewMatrix;
				role.indexBuffer = this._indexBuffer;
				role.x = 1300*Math.random();
				role.y = 720*Math.random();
				roleList.push(role);
			}
			
			newrole = new Role(_context3D,arymodel[int(7*Math.random())]);
			newrole.viewMatrix = _viewMatrix;
			newrole.indexBuffer = this._indexBuffer;
			newrole.x = 1200;
			newrole.y = 400;
			
			/*initList();
			addEventListener(Event.ENTER_FRAME, renderFrame)*/
		}
		private var roleList:Vector.<Role> = new Vector.<Role>;
		public function initMatrix():void{
			_viewMatrix = new Matrix3D();
			_viewMatrix.appendTranslation(-stage.stageWidth/2, -stage.stageHeight/2, 0);
			_viewMatrix.appendScale(1, -1, 1);
			_viewMatrix.append(new Matrix3D(Vector.<Number>
				([
					2/stage.stageWidth, 0  ,       0,        0,
					0  , 2/stage.stageHeight,       0,        0,
					0  , 0  , 1/100, 0,
					0  , 0  ,       0,        1
				])));
		}
		public function initMap(mapName:String):void{
			this._mapName = mapName;
			
			var loadList:Vector.<LoadInfo> = new Vector.<LoadInfo>;
			var mapdataUrl:String = _baseUrl + _mapName + "/" + _mapName + ".navmap";
			var loadInfo:LoadInfo = new LoadInfo(mapdataUrl,LoadInfo.XML,onLoadmapData,true);
			loadList.push(loadInfo);
			
			var miniMapUrl:String = _baseUrl + _mapName + "/minimap/" + _mapName + ".jpg";
			loadInfo = new LoadInfo(miniMapUrl,LoadInfo.BITMAP,onLoadMiniMap,true);
			loadList.push(loadInfo);
			
			stage.addChild(MapLoaderInterface.getInstance());
			LoadManager.getInstance().addListLoad(loadList,onMapLoaded);
			
			_mapdataDIC = new Object;
		}
		
		private function onLoadmapData(xml:XML):void{
			this._mapWidth = xml.@mapwidth;
			this._mapHeight = xml.@mapheight;
			this._pich = xml.@pich;
			this._picw = xml.@picw;
			initMapData(xml.@mapdata,xml.@blockdata);
		}
		
		private function initMapData(trgData:String,blockData:String):void{
			var cell:Cell;
			var ary:Array = trgData.split('|');
			var str:String;
			var pAry:Array
			for(var i:int=0;i<ary.length;i++){
				str = ary[i];
				pAry = str.split(',');
				cell = new Cell(new Vector2f(pAry[0],pAry[1]),new Vector2f(pAry[2],pAry[3]),new Vector2f(pAry[4],pAry[5]));
				cell.index = i;
				for(var j:int=6;j<pAry.length;j++){
					cell.bolckAry = new Vector.<int>;
					cell.bolckAry.push(pAry[j]);
				}
				_cellV.push(cell);
			}
			linkCells(_cellV);
			
			ary = blockData.split('//');
			
			for(i=0;i<ary.length;i++){
				str = ary[i];
				pAry = str.split('|');
				var vAry:Vector.<Vector2f> = new Vector.<Vector2f>;
				for(j=0;j<pAry.length;j++){
					str = pAry[j];
					var bAry:Array = str.split(",");
					var v2f:Vector2f = new Vector2f(bAry[0],bAry[1]);
					vAry.push(v2f);
				}
				_blockV.push(new Block(vAry));
			}
			nav = new NavMesh(_cellV);
			_mapContainer.nav = nav;
			nav.blockV = _blockV;
			stage.addChild(nav);
			//_mapContainer.setNav(_cellV,_blockV);
		}
		public function linkCells(pv:Vector.<Cell>):void {
			for each (var pCellA:Cell in pv) {
				for each (var pCellB:Cell in pv) {
					if (pCellA != pCellB) {
						pCellA.checkAndLink(pCellB);
					}
				}
			}
		}
		
		private function onLoadMiniMap(bitmap:Bitmap):void{
			//_mapContainer.mapBitmap = bitmap;
			_mapContainer.bitmapdata = bitmap.bitmapData;
		}
		
		private function onMapLoaded(event:Event):void{
			stage.removeChild(MapLoaderInterface.getInstance());
			_mapContainer.setMapWH(3000,1800); 
			initListDIC();
			stage.addEventListener(Event.ENTER_FRAME,enFrame);
		}
		private function initListDIC():void{
			if(_loadListDIC == null)
				_loadListDIC = new Object;
			var w:int = Math.ceil(_mapWidth/256);
			var h:int = Math.ceil(_mapHeight/256);
			_allNum = w*h;
			for(var i:int=0;i<w;i++){
				for(var j:int=0;j<h;j++){
					var key:String = i + "_" + j;
					_loadListDIC[key] = false;
				}
			}
			
		}
		
		private function onLoadAll():void{
			for(var i:int=0;i<10;i++){
				for(var j:int=0;j<6;j++){
					var key:String = i + "_" + j + ".jpg";
					var url:String = _baseUrl + _mapName + "/newimg/" + key;
					var loadInfo:LoadInfo = new LoadInfo(url,LoadInfo.BITMAP,refreshBitmap,false,new Point(i,j));
					LoadManager.getInstance().addSingleLoad(loadInfo);
				}
			}
		}
		public function onLoadkey(xpos:Number,ypos:Number,wNum:int,hNum:int):void{
			if(_loadNum >= _allNum){
				//Console.getInstance().show("加载全部完成");
				return;
			}
			var key:String;
			var beginX:int = xpos/256;
			var beginY:int = ypos/256;
			
			key = beginX + "_" + beginY;
			
			if(_currentPoint != key){
				Console.getInstance().show("加载");
				_currentPoint = key;
			}else{
				Console.getInstance().show("空闲");
				return;
			}
			
			for(var i:int=0;i<wNum;i++){
				for(var j:int=0;j<hNum;j++){
					key = (i+beginX) + "_" + (j+beginY);
					if(!_loadListDIC.hasOwnProperty(key) || _loadListDIC[key]){
						continue;
					}
					var url:String = _baseUrl + _mapName + "/imgMolehill/" + key + ".jpg";
					_loadListDIC[key] = true;
					_loadNum++;
					if(_loadNum == 49){
						Console.getInstance().show("complete");
					}
					var loadInfo:LoadInfo = new LoadInfo(url,LoadInfo.BITMAP,refreshBitmap,false,new Point(i+beginX,j+beginY));
					LoadManager.getInstance().addSingleLoad(loadInfo);
				}
			}
			
		}
		public function resizeStage():void{
			trace(_context3D.driverInfo);
			try
			{
				_context3D.configureBackBuffer(stage.stageWidth, stage.stageHeight, 2, false);		
			}
			catch (e:Error)
			{
				trace(e);
			}
			initMatrix();
			_mapContainer.viewMatrix = _viewMatrix;
			
		}
		private function refreshBitmap(bitmap:Bitmap,p:Point):void{
			//var bitmapdata:BitmapData = _mapContainer.bitmapdata;
			//var newbitmapdata:BitmapData = bitmap.bitmapData;
			//var rec:Rectangle = new Rectangle(0,0,256,256);
			var newp:Point = new Point(p.x * 256,p.y * 256);
			//bitmapdata.copyPixels(newbitmapdata,rec,newp);
			_mapContainer.refreshBitmap(bitmap.bitmapData,newp);
		}
		
		private static function makeOrthoProjection(w:Number, h:Number, n:Number, f:Number):Matrix3D
		{
			return new Matrix3D(Vector.<Number>
				([
					2/w, 0  ,       0,        0,
					0  , 2/h,       0,        0,
					0  , 0  , 1/(f-n), -n/(f-n),
					0  , 0  ,       0,        1
				]));
		}
		
		
		
		private var num:Number = 340;
		private var numy:Number = 0;
		private function enFrame(event:Event):void{
			num += 1;
			numy += 1;
			if(num>=1090){
				num = 340;
			}
			if(numy > 800){
				numy = 1;
			}
			//_mapContainer.refrushMap(new Point(num*_mapWidth/stage.stageWidth,numy*_mapHeight/stage.stageHeight));
			_mapContainer.refrushMap(new Point(stage.mouseX*_mapWidth/stage.stageWidth,stage.mouseY*_mapHeight/stage.stageHeight));
			//t++;
			//_mapContainer.refrushMap(new Point(300,200));
			_context3D.clear(0, 1, 0, 0);
			_mapContainer.render();
			for(var i:int;i<roleList.length;i++){
				role = roleList[i];
				role.x++;
				role.y++;
				role.render();
				if(role.x>1100){
					role.x = 0;
				}
				if(role.y > 720){
					role.y = 0;
				}
				role.render();
			}
			newrole.render();
			_context3D.present();
		}
		
		
	}
}